// 第八章 8.2 使用constexpr计算

// constexpr是C++11引入的一个关键特性，它在模板元编程中具有重要作用。
// 以下是对这部分内容的详细讲解：

// 1. constexpr基础概念
// constexpr关键字用于声明可以在编译时计算的函数或变量。它有几个关键特点：
// 允许在编译时执行计算
// 可以用于类型和非类型模板参数
// 比传统的模板元编程更直观、更易读

// 2. constexpr函数
constexpr int square(int x)
{
    return x * x;
}

// 编译时计算
constexpr int result = square(5); // 结果是25，在编译时计算

// 3. constexpr与模板结合
template <typename T>
constexpr T power(T base, unsigned exp)
{
    return (exp == 0) ? 1 : base * power(base, exp - 1);
}

// 编译时使用
constexpr auto result = power(2, 10); // 1024，编译时计算

// 4. constexpr类和方法
class Point
{
private:
    int x, y;

public:
    constexpr Point(int x_, int y_) : x(x_), y(y_) {}

    constexpr int getX() const { return x; }
    constexpr int getY() const { return y; }

    constexpr Point operator+(const Point &other) const
    {
        return Point(x + other.x, y + other.y);
    }
};

// 编译时使用
constexpr Point p1(1, 2);
constexpr Point p2(3, 4);
constexpr Point p3 = p1 + p2; // 在编译时计算 Point(4, 6)
constexpr int x = p3.getX();  // 编译时获得 4

// 5. constexpr与条件语句
// C++14扩展了constexpr函数的能力，允许使用更多语句：
constexpr int factorial(int n)
{
    int result = 1;
    for (int i = 1; i <= n; ++i)
    { // C++14允许在constexpr中使用循环
        result *= i;
    }
    return result;
}

constexpr int fact5 = factorial(5); // 120，编译时计算

// 6. constexpr与模板元编程的比较
// 传统模板元编程：
template <int N>
struct Factorial
{
    static const int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0>
{
    static const int value = 1;
};

int result = Factorial<5>::value; // 120

// 使用constexpr：
constexpr int factorial(int n)
{
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

constexpr int result = factorial(5); // 120


// 7. 编译时计算的优势
// 性能提升：计算在编译时完成，运行时无需重复计算
// 优化机会：编译器可以基于常量值进行更多优化
// 代码简化：避免了复杂的模板元编程技术


// 8. constexpr的限制
// C++11中constexpr函数只能包含一条return语句（C++14放宽了这一限制）
// constexpr函数中不能有副作用
// 不是所有操作都可以在constexpr中执行（如动态内存分配）